<?php
class parser
{
    public $input;
    /**
    * @desc init
    * @access   public
    * @param    void
    * @return   void
    */
    public function init()
    {
        $this->_get_input_stream();   
    }
    /**
    * @desc Get an environment variable value, Abstr
    * act layer allows us to user $_SERVER or getenv()
    * @access   public
    * @param    string  $key
    * @return   string
    */
    public function my_getenv($key)
    {
        $return = array();

        if ( is_array( $_SERVER ) AND count( $_SERVER ) )
        {
            if( isset( $_SERVER[$key] ) )
            {
                $return = $_SERVER[$key];
            }
        }

        if ( ! $return )
        {
            $return = getenv($key);
        }

        return $return;
    }
    /**
    * @desc  clean memory, push and parse input data to process stream
    * @access   private
    * @param    void
    * @return   void
    * @internal
    */
    private function _get_input_stream()
    {
        /**
        * clean globals
        */
        $this->clean_globals( $_GET );
        $this->clean_globals( $_POST );
        $this->clean_globals( $_COOKIE );
        $this->clean_globals( $_REQUEST );


        //===========================================================================
        // get input
        //===========================================================================

        /**
        * _GET
        */
        $input = $this->parse_incoming( $_GET, array() );

        /**
        * _POST
        */
        $input = $this->parse_incoming( $_POST, $input );

        /**
        * push it
        */
        $this->input = $input;

        /**
        * release
        */
        unset( $input );

        /**
        * Assign request method
        */
        $this->input['request_method'] = strtolower($this->my_getenv('REQUEST_METHOD'));
    }
    /**
    * @desc Performs basic cleaning, Null-characters etc
    * @access   public
    * @param    pointer &$data
    * @param    integer    $interation
    * @return   void
    */
    public function clean_globals( &$data, $iteration = 0 )
    {
        /**
        * keep global array < 10
        */
        if( $iteration >= 10 )
        {
            return $data;
        }

        if( count( $data ) )
        {
            foreach( $data as $k => $v )
            {
                if ( is_array( $v ) )
                {
                    $this->clean_globals( $data[ $k ], $iteration++ );
                }
                else
                {
                    /**
                    * Null byte characters
                    */
                    $v = preg_replace( '/\\\0/' , '', $v );
                    $v = preg_replace( '/\\x00/', '', $v );
                    $v = str_replace( '%00'     , '', $v );

                    /**
                    * File traversal
                    */
                    $v = str_replace( '../'    , '&#46;&#46;/', $v );

                    $data[ $k ] = $v;
                }
            }
        }
    }

    /**
    * @desc Recursively cleans keys and values and inserts them into the input array
    * @access   public
    * @param    param   &$data
    * @param    array   $input
    * @param    integer    $interation
    * @return   void
    */
    public function parse_incoming( &$data, $input=array(), $iteration = 0 )
    {
        /**
        * keep global array < 20
        */

        /*if( $iteration >= 20 )
        {
            return $input;
        }*/

        if( count( $data ) )
        {
            foreach( $data as $k => $v )
            {
                if ( is_array( $v ) )
                {
                    $input[ $k ] = $this->parse_incoming( $data[ $k ], array(), $iteration++ );
                }
                else
                {
                    /**
                    * clean
                    */
                    $k = $this->parse_clean_key( $k );
                    $v = $this->parse_clean_value( $v );

                    if (is_array($v)){
                        $input[ $k ] = $v;
                    }
                    else {
                        if( 1 === preg_match('/^[+-]?[0-9]+$/', $v) )
                        {
                            $input[ $k ] = intval($v);
                        }
                        else {
                            $input[ $k ] = $v;
                        }
                    }
                }
            }
        }

        return $input;
    }

    /**
    * @desc Key Cleaner - ensures no funny business with form elements
    * @access   public
    * @param    string  $key
    * @return   string
    */
    public function parse_clean_key($key)
    {
        if ($key == "")
        {
            return 0;
        }
        $key = htmlspecialchars(urldecode($key));
        $key = str_replace( ".."           , ""  , $key );
        $key = preg_replace( "/\_\_(.+?)\_\_/"  , ""  , $key );
        $key = preg_replace( "/^([\w\.\-\_]+)$/", "$1", $key );

        return $key;
    }

    /**
    * @desc UnHTML and stripslashes _GET _POST value
    * @access   public
    * @param    string  $val
    * @return   string
    */
    public function parse_clean_value($val)
    {
        if ( $val == "" )
        {
            return "";
        }

        $val = str_replace( "&#032;", " ", $this->txt_stripslashes($val) );

        /*if ( $this->kernel->config->get_global_config('module_strip_space_chr'))
        {
            /**
            * Remove sneaky spaces
            /
            $val = str_replace( chr(0xCA), "", $val );
        }         */

        $val = str_replace( "&"                , "&amp;"         , $val );

        /**
        * special HTML char
        */

        $val = $this->safe_html_encode($val);

        /**
        * Remove literal carriage returns
        */
        $val = str_replace( "\r"            , ""              , $val );

        /**
        * IMPORTANT: It helps to increase sql query safety.
        */
        $val = str_replace( "'"                , "&#39;"         , $val );

        /**
        * Ensure unicode chars are OK
        */
        $val = preg_replace("/&amp;#([0-9]+);/s", "&#\\1;", $val );

        //-----------------------------------------
        // Try and fix up HTML entities with missing ;
        //-----------------------------------------

        $val = preg_replace( "/&#(\d+?)([^\d;])/i", "&#\\1;\\2", $val );


        return $val;
    }

    /**
    * @desc Remove slashes if magic_quotes enabled
    * @access   public
    * @param    string  $t
    * @return   string
    */
    public function txt_stripslashes($t)
    {
        if ( $this->kernel->system->use_magic_quotes)
        {
            $t = stripslashes($t);
            $t = preg_replace( "/\\\(?!&amp;#|\?#)/", "&#092;", $t );
        }

        return $t;
    }

    /**
    * Get the true length of a multi-byte character string
    *
    * @param    string    Input String
    * @return    intger    String length
    */
    function txt_mb_strlen( $t )
    {
        return strlen( preg_replace("/&#([0-9]+);/", "-", $this->txt_stripslashes( $t ) ) );
    }

    /**
    *   @desc        substring for multibyte
    *
    *   @access        public
    *    @param        string
    *     @param        integer
    *     @param        integer
    *     @param        string
    *   @returns    string
    */
    function txt_mbsubstr($text, $start=0, $limit=30, $charset='utf-8')
    {
        $text = str_replace( '&amp;' , '&#38;', $text );
        $text = str_replace( '&quot;', '&#34;', $text );
        return mb_substr( $text, $start, $limit, strtoupper($charset) );
    }

    /**
    *   @desc        make real HTML to safe HTML
    *
    *   @access        public
    *    @param        string
    *   @returns    string
    */
    function safe_html_encode($val){
        $val = str_replace( "<!--"            , "&#60;&#33;--"  , $val );
        $val = str_replace( "-->"            , "--&#62;"       , $val );
        $val = preg_replace( "/<script/i"    , "&#60;script"   , $val );
        $val = str_replace( ">"                , "&gt;"          , $val );
        $val = str_replace( "<"                , "&lt;"          , $val );
        $val = str_replace( '"'                , "&quot;"        , $val );
        $val = str_replace( "$"                , "&#036;"        , $val );
        return $val;
    }

    /**
    *   @desc        make safe HTML to real HTML
    *
    *   @access        public
    *    @param        string
    *   @returns    string
    */
    public function safe_html_decode($val){
        $val = str_replace("&#60;&#33;--"    ,  "<!--"     , $val );
        $val = str_replace("--&#62;"         ,  "-->"      , $val );
        $val = str_replace("&gt;"            ,  ">"        , $val );
        $val = str_replace("&lt;"            ,  "<"        , $val );
        $val = str_replace("&amp;"           ,  "&"        , $val );
        $val = str_replace("&#39;"           ,   "'"       , $val );
        $val = str_replace("&quot;"          , '"'         , $val );
        return $val;
    }

    /**
    *   @desc        clean MS Office HTML
    *
    *   @access        public
    *    @param        string
    *   @returns    string
    */
    public function tidy_msoffice_html($value){
        /*$value = str_replace('<o:p>&nbsp;</o:p>', '' , $value );*/
        /*$value = str_replace('<o:p></o:p>', '' , $value );*/
        $value = str_replace('style="margin: 0cm 0cm 0pt;"', "" , $value );
        $value = str_replace('>&nbsp;<', "><" , $value );
        return $value;
    }

    /**
    *   @desc        filter emo for a HTML string
    *
    *   @access        public
    *    @param        string
    *     @param        array
    *   @returns    string
    */
    public function filter_emo($value, $emo_list=array()){
        return $value;
    }

    /**
    *   @desc        clean HTML tag
    *
    *   @access        public
    *    @param        string
    *     @param        array
    *   @returns    string
    */
    public function strip_htmltags($value, $allowable_tags=array()){
        $allowed_tags = '';
        foreach($allowable_tags as $html_tag)
        {
            $allowed_tags .= '<'.$html_tag.'>';
        }
        return strip_tags($value, $allowed_tags);
    }

    /**
    *   @desc        clean HTML tag attributes
    *
    *   @access        public
    *    @param        string
    *     @param        array
    *   @returns    string
    */
    public function strip_attributes($value, $bad_attributes=array()){

        $bad_attrib_str = '';
        foreach($bad_attributes as $tag_attribute)
        {
            $bad_attrib_str .= ' '.$tag_attribute.'="(.*?)"|';
        }
        $bad_attrib_str = substr($bad_attrib_str, 0, strlen($bad_attrib_str) - 1);

        $result  = '';
        $regex   = '/('.$bad_attrib_str.')/ie';
        $regex_item = "preg_replace('$regex','','\\1')";
        $result = preg_replace($regex, '', $value);
        //$result  = preg_replace('/<(.*?)>/ie',"'<'.$regex_item.'>'",$string);
        return $result;
    }

    /**
    *   @desc        check HTML length
    *
    *   @access        public        $value                a safe HTML string, cleaned by LBP before
    *    @param        string
    *     @param        integer        $pos                position that define maximum length of the HTML
    *   @returns    boolean        true if the length is not over maximum
    */
    public function check_html_length($value="", $pos){
        if ($value == "") return true;
        /**
        *    convert everything back to HTML
        */
        $value = $this->safe_html_decode($value);
        $length = $this->txt_mb_strlen($value);
        if ($length > $pos){
            return false;
        }
        else {
            return true;
        }
    }

    /**
    *   @desc       check minimum content
    *
    *   @access        public
    *    @param        string        $value                a safe HTML string, cleaned by LBP before
    *     @param        integer        $pos                position that define minimum length of the content
    *   @returns    boolean        true if the length is over minimum
    */
    public function check_min_content_length($value, $pos=0){
        /**
        *    convert everything back to HTML
        */
        $value = $this->safe_html_decode($value);
        $value = trim(strip_tags($value));
        $length = $this->txt_mb_strlen($value);
        if ($length <= $pos){
            return false;
        }
        else {
            return true;
        }
    }

    /**
    *   @desc        make a safe HTML into HTML that is tidied and cleaned
    *
    *   @access        public
    *    @param        string        $value                a safe HTML string, cleaned by LBP before
    *     @param        integer        $cut_pos            position that we will cut the HTML, count by mb char
    *     @param        boolean        $use_emo            will we convert emo for this HTML?
    *     @param        array        $allowable_tags        array that contains HTML tag that is allowed, empty array will allow all
    *     @param        array        $bad_attributes        array that contains HTML tag attributes that is allowed, empty array will allow all
    *   @returns    string        HTML string that is tidied, cleaned, beautified :D
    */
    public function tidy_html($value="", $cut_pos=null, $use_emo=false, $allowable_tags=array(), $bad_attributes=array()){
        if ($value == "") return;
        /**
        *    convert everything back to HTML
        */
        $value = $this->safe_html_decode($value);

        /**
        *    clean msoffice html that is left
        */
        $value = $this->tidy_msoffice_html($value);

        /**
        *    cut the string if it is too long
        */
        if ($cut_pos != null ) {
            $cut_pos = intval($cut_pos);
            if ($cut_pos != 0){
                $value = $this->txt_mbsubstr($value, 0, $cut_pos);
            }
        }

        /**
        *    clean not allowed HTML
        */
        $value = str_replace("\n", ' ', $value);
        if (count($allowable_tags) > 0){
            $value = $this->strip_htmltags($value, $allowable_tags);
        }

        if (count($bad_attributes) > 0){
            $value = $this->strip_attributes($value, $bad_attributes);
        }

        /**
        *    tidy
        */

        $options = array(
            "output-html"         =>     true,
            "show-body-only"     =>    true,
            "hide-comments"        =>    true,
            "word-2000"            =>    true,
            "output-encoding"    =>    "utf8",
            "input-encoding"    =>    "utf8",
        );
        $value = str_replace('&nbsp;', "(olala)" , $value );
        $tidy = tidy_parse_string($value, $options);
        tidy_clean_repair($tidy);
        $value = $tidy;
        $value = str_replace( "(olala)", "&nbsp;" , $value );
        $value = str_replace( "\n", " " , $value );

        /**
        *    convert emo
        */

        $value = $this->filter_emo($value);

        /**
        *    return
        */

        return $value;
    }

    /**
    *   @desc        return the sring that all vietnamese chars have been stripped off
    *
    *   @access        public
    *    @param        string
    *   @returns    string
    */
    public function remove_vietnamese($input_str){
        $marTViet=array("à","á","ạ","ả","ã","â","ầ","ấ","ậ","ẩ","ẫ","ă",
        "ằ","ắ","ặ","ẳ","ẵ","è","é","ẹ","ẻ","ẽ","ê","ề"
        ,"ế","ệ","ể","ễ",
        "ì","í","ị","ỉ","ĩ",
        "ò","ó","ọ","ỏ","õ","ô","ồ","ố","ộ","ổ","ỗ","ơ"
        ,"ờ","ớ","ợ","ở","ỡ",
        "ù","ú","ụ","ủ","ũ","ư","ừ","ứ","ự","ử","ữ",
        "ỳ","ý","ỵ","ỷ","ỹ",
        "đ",
        "À","Á","Ạ","Ả","Ã","Â","Ầ","Ấ","Ậ","Ẩ","Ẫ","Ă"
        ,"Ằ","Ắ","Ặ","Ẳ","Ẵ",
        "È","É","Ẹ","Ẻ","Ẽ","Ê","Ề","Ế","Ệ","Ể","Ễ",
        "Ì","Í","Ị","Ỉ","Ĩ",
        "Ò","Ó","Ọ","Ỏ","Õ","Ô","Ồ","Ố","Ộ","Ổ","Ỗ","Ơ"
        ,"Ờ","Ớ","Ợ","Ở","Ỡ",
        "Ù","Ú","Ụ","Ủ","Ũ","Ư","Ừ","Ứ","Ự","Ử","Ữ",
        "Ỳ","Ý","Ỵ","Ỷ","Ỹ",
        "Đ");

        $marKoDau=array("a","a","a","a","a","a","a","a","a","a","a"
        ,"a","a","a","a","a","a",
        "e","e","e","e","e","e","e","e","e","e","e",
        "i","i","i","i","i",
        "o","o","o","o","o","o","o","o","o","o","o","o"
        ,"o","o","o","o","o",
        "u","u","u","u","u","u","u","u","u","u","u",
        "y","y","y","y","y",
        "d",
        "A","A","A","A","A","A","A","A","A","A","A","A"
        ,"A","A","A","A","A",
        "E","E","E","E","E","E","E","E","E","E","E",
        "I","I","I","I","I",
        "O","O","O","O","O","O","O","O","O","O","O","O"
        ,"O","O","O","O","O",
        "U","U","U","U","U","U","U","U","U","U","U",
        "Y","Y","Y","Y","Y",
        "D");

        return str_replace($marTViet, $marKoDau, $input_str);
    }

    function sort_array_by_key($data, $key, $order="DESC")
    {
        $result = $data;

        // parser
        if ( is_array( $result ) )
        {
            if ( ! count($result) )
            {
                return false;
            }
        }

        if(empty($key))
        {
            return false;
        }

        foreach($result as $idd=>$valued)
        {

            foreach($result as $idt=>$valuet)
            {
                if($idt <= $idd )
                {
                    continue;
                }
                if($order == "DESC")
                {
                    if($valued[$key] < $valuet[$key])
                    {
                        $tmp = $result[$idd];
                        $result[$idd] = $result[$idt];
                        $result[$idt] = $tmp;
                    }
                }
                else
                {
                    if($valued[$key] > $valuet[$key])
                    {
                        $tmp = $result[$idd];
                        $result[$idd] = $result[$idt];
                        $result[$idt] = $tmp;
                    }
                }
            }
        }

        return $result;
    }

    public function parse_linebreak_to_html($value){
        return str_replace("\n", "<br/>", $value);
    }

    public function strip_url_special_chars($text){
        $special_chars     = array(" - ", " -", "- ", " ",    "/", "?", "&", "\$", "#", '“', '”', '[', ']', ':', '%', '!','.');
        $to_chars        = array("-"  , "-" , "-" , "-", "-", "", ""  , ""  , "" , "" , "" , "" , "" , "" , "" , "" ,"" );
        $text = strtolower($text);
        return str_replace($special_chars, $to_chars, $text);
    }

    public function filter_search_keywords($words="")
    {
        /**
        * force to lowercase and swop % into a safer version
        */
        $words = trim( rawurldecode($words) );
        $words = str_replace( '|', "&#124;", $words );

        /**
        * Remove crap
        */
        $words = str_replace( "&quot;", '"', $words );
        $words = str_replace( "&gt;"  , ">", $words );
        $words = str_replace( "%"     , "" , $words );

        //-----------------------------------------
        // If it's a phrase in quotes..
        //-----------------------------------------

        if ( preg_match( "#^\"(.+?)\"$#", $words ) )
        {
            return $words;
        }

        /**
        * Remove common words..
        */
        $words = preg_replace( "/^(?:img|quote|code|html|javascript|a href|color|span|div|border|style)$/", "", $words );

        /**
        * break up the keywords
        */
        $words = preg_replace( "/\s+and\s+/i", " ", $words );

        /**
        * this or that this not me
        */
        $words = preg_replace( "/\s+not\s+/i", " -", $words );

        /**
        * this or that this -me
        */
        $words = preg_replace( "/\s+or\s+/i", ' ~', $words );

        /**
        * this ~that +this -me
        */

        $words = str_replace( "~", "", $words );

        /**
        * this that +this -me
        */
        return "+".$words;
    }

    public function calculate_file_size($file_size){
        $one_kb = 1024;
        $one_mb = 1024 * 1024;

        if ($file_size < $one_kb){
            $unit = 'byte';
            $num = $file_size;
        }
        else if ($file_size >= $one_kb && $file_size < $one_mb){
            $unit = 'KB';
            $num = round($file_size / $one_kb, 1);
        }
        else if ($file_size >= $one_mb){
            $unit = 'MB';
            $num = round($file_size / $one_mb, 1);
        }

        return $num . ' ' . $unit;
    }
}
?>
